/* eslint-disable func-names */
const path = require('path');
const glob = require('glob');
// const HappyPack = require('happypack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
// const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default;
// const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
// const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
// require('webpack-bundle-analyzer') 导入的是一个对象
// require('webpack-bundle-analyzer').BundleAnalyzerPlugin 才是构造函数
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserPlugin = require('terser-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
// const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const PurgecssPlugin = require('purgecss-webpack-plugin');
const webpack = require('webpack');

const PATHS = {
  src: path.join(__dirname, 'src'),
};

// const smp = new SpeedMeasureWebpackPlugin();
// 动态设置entry和htmlwebpackplugin
const setMPA = () => {
  const entry = {};
  const htmlWebpackPlugins = [];
  // ['C:/Users/xxx/src/index/index.js','C:/Users/xxx/src/search/index.js']
  const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js'));
  Object.keys(entryFiles).map((index) => {
    // 'C:/Users/xxx/src/search/index.js'
    const entryFile = entryFiles[index];
    // [
    //   'src/search/index.js',
    //   'search',
    //   index: 81,
    //   input: 'C:/Users/xxx/src/search/index.js',
    //   groups: undefined
    // ]
    const match = entryFile.match(/src\/(.*)\/index\.js/);
    const pageName = match && match[1];
    entry[pageName] = entryFile;
    htmlWebpackPlugins.push(new HtmlWebpackPlugin({
      template: path.join(__dirname, `src/${pageName}/index.html`),
      filename: `${pageName}.html`,
      // 指定生成的html要使用哪些chunk
      // 要使用分包的chunk，需要额外指定
      // 顺序一般是基础库、公共业务、页面对应chunk
      chunks: ['library.dll', 'vendors', 'commons', pageName],
      // css、js自动注入到html中
      inject: true,
      // minify: {
      //   html5: true,
      //   collapseWhitespace: true,
      //   preserveLineBreaks: false,
      //   minifyCSS: true,
      //   minifyJS: true,
      //   removeComments: false,
      // },
    }));
  });

  return {
    entry,
    htmlWebpackPlugins,
  };
};

const { entry, htmlWebpackPlugins } = setMPA();

module.exports = {
  // 生产模式不需要热更新
  // watch: true,
  // watchOptions: {
  //     ignored: /node_modules/,
  //     aggregateTimeout: 300,
  //     poll: 1000,
  // },
  entry,
  // entry: {
  //   index: "./src/index/index.js",
  //   search: "./src/search/index.js",
  // },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]_[contenthash:8].js',
  },
  mode: 'production',
  module: {
    rules: [
      {
        test: /.js$/,
        // 指定babel-loader只处理src目录下的文件
        // 必须要指定绝对路径，path.resolve就是生成绝对路径
        include: path.resolve('src'),
        // exclude: path.resolve('node_modules'),
        use: [
          // {
          //   loader: 'thread-loader',
          //   options: {
          //     workers: 3,
          //   },
          // },
          // 'happypack/loader',
          // 'cache-loader',
          {
            loader: 'babel-loader',
            options: {
              // 开启缓存
              // cacheDirectory: true,
              // 是否压缩缓存文件。false不压缩，可以提高缓存读写速度，但会占用更多磁盘空间
              // cacheCompression: false,
            },
          },
          // 'babel-loader',
          'eslint-loader',
        ],
      },
      {
        test: /.css$/,
        use: [
          // style-loader 和 MiniCssExtractPlugin.loader功能互斥，不能同时使用
          // style-laoder是把css样式插入到head标签中，MiniCssExtractPlugin.loader是把css样式提取到单独的文件中
          // MiniCssExtractPlugin生成的css文件不会自动引入到js文件中，需要手动引入，可以用html-webpack-plugin插件自动引入
          // 'style-loader',
          {
            loader: 'style-loader',
            options: {
              // 样式插入到head标签顶部，bottom就是head的底部
              insertAt: 'bottom',
              // 将style标签合并成一个
              singleton: false,
            },
          },
          //   MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: () => [
                require('autoprefixer')({
                  browsers: ['last 6 version', '>1%', 'ios 4'],
                }),
              ],
            },
          },
          {
            loader: 'px2rem-loader',
            options: {
              // 1rem等于75px，比较适合750px的设计稿，10rem
              remUnit: 75,
              // px转换成rem的小数点后位数
              remPrecision: 8,
            },
          },
        ],
      },
      {
        test: /.(png|jpg|gif|jpeg)$/,
        use: [
          // {
          //     loader: 'url-loader',
          //     options: {
          //         limit: 10240
          //     }
          // }
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
            },
          },
          // "image-webpack-loader": "^8.1.0",
          // "imagemin-gifsicle": "^7.0.0",
          // "imagemin-mozjpeg": "^10.0.0",
          // "imagemin-optipng": "^8.0.0",
          // "imagemin-pngquant": "^10.0.0",
          // {
          //   loader: 'image-webpack-loader',
          //   options: {
          //     mozjpeg: {
          //       progressive: true,
          //     },
          //     // optipng.enabled: false will disable optipng
          //     optipng: {
          //       enabled: false,
          //     },
          //     pngquant: {
          //       quality: [0.65, 0.90],
          //       speed: 4,
          //     },
          //     gifsicle: {
          //       interlaced: false,
          //     },
          //     // the webp option will enable WEBP
          //     webp: {
          //       quality: 75,
          //     },
          //   },
          // },
        ],
        // use: 'file-loader'
      },
      {
        test: /.(woff|woff2|eot|ttf|otf)$/,
        // use: 'file-loader'
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name]_[contenthash:8].css',
    }),
    new OptimizeCSSAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require('cssnano'),
    }),
    ...htmlWebpackPlugins,
    // new HtmlWebpackPlugin({
    //   template: path.join(__dirname, "src/index/index.html"),
    //   filename: "index.html",
    //   // 指定生成的html要使用哪些chunk
    //   chunks: ["index"],
    //   // css、js自动注入到html中
    //   inject: true,
    //   minify: {
    //     html5: true,
    //     collapseWhitespace: true,
    //     preserveLineBreaks: false,
    //     minifyCSS: true,
    //     minifyJS: true,
    //     removeComments: false,
    //   },
    // }),
    // new HtmlWebpackPlugin({
    //   template: path.join(__dirname, "src/search/index.html"),
    //   filename: "search.html",
    //   // 指定生成的html要使用哪些chunk
    //   chunks: ["search"],
    //   // css、js自动注入到html中
    //   inject: true,
    // //   minify: {
    // //     html5: true,
    // //     collapseWhitespace: true,
    // //     preserveLineBreaks: false,
    // //     minifyCSS: true,
    // //     minifyJS: true,
    // //     removeComments: false,
    // //   },
    // }),
    // new HTMLInlineCSSWebpackPlugin(),
    // 将资源文件以script标签形式加入到html文件中
    new AddAssetHtmlPlugin([
      { filepath: require.resolve('./library/libraryCai.dll.js') },
    ]),
    new CleanWebpackPlugin(),
    new FriendlyErrorsWebpackPlugin(),
    function () {
      this.hooks.done.tap('done', (stats) => {
        if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') === -1) {
          console.log('build error');
          process.exit(1);
        }
      });
    },
    // new BundleAnalyzerPlugin(),
    // new HappyPack({
    //   loaders: ['babel-loader'],
    // }),
    new webpack.DllReferencePlugin({
      manifest: require('./library/libraryCai-manifest.json'),
    }),
    new PurgecssPlugin({
      // nodir: true 确保只返回文件路径，而不包括目录路径
      paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
    }),
    // new HardSourceWebpackPlugin(),
    // 通过CDN方式引入react和react-dom基础包，不打入bundle中
    // new HtmlWebpackExternalsPlugin({
    //   externals: [
    //     {
    //       // 指定要引入的模块名称，和 import ... from "xxx" 中的 xxx 对应
    //       module: 'react',
    //       // 模块的加载地址
    //       entry: 'https://unpkg.com/react@16/umd/react.development.js',
    //       // 指定模块在全局作用域中的变量名
    //       global: 'React',
    //     },
    //     {
    //       module: 'react-dom',
    //       entry: 'https://unpkg.com/react-dom@16/umd/react-dom.development.js',
    //       global: 'ReactDOM',
    //     },
    //   ],
    // }),
  ],
  optimization: {
    splitChunks: {
      // 最小体积，包大小大于minSize才会提取出来，单位是Bytes字节
      minSize: 0,
      cacheGroups: {
        // 提取基础包
        vendors: {
          test: /(react|react-dom)/,
          // test: /[\\/]node_modules[\\/](react|react-dom)/,
          // 如果要使用，需要把name对应的属性添加到htmlWebpackPlugin的chunk参数数组里
          name: 'vendors',
          chunks: 'all',
        },
        // 提取公共业务模块
        commons: {
          name: 'commons',
          chunks: 'all',
          // 至少引用2次才提取
          minChunks: 2,
        },
      },
    },
    minimizer: [
      new TerserPlugin({
        parallel: true,
        cache: true,
      }),
    ],
  },
  // devtool: 'inline-source-map'
  // stats: 'errors-only',
  resolve: {
    // 指定查找路径，直接到指定路径查找React，减少查找时间
    alias: {
      react: path.resolve(__dirname, './node_modules/react/umd/react.production.min.js'),
      'react-dom': path.resolve(__dirname, './node_modules/react-dom/umd/react-dom.production.min.js'),
    },
    // 没有后缀名的文件，去寻找文件名加.js的文件
    extensions: ['.js'],
    // 查找package.json的main字段内容作为入口文件
    mainFields: ['main'],
    // 添加modules字段，指定模块查找的目录顺序
    modules: [path.resolve(__dirname, 'src'), 'node_modules'],
  },
};
